<?php namespace testsacvoyage\storage;



require_once 'testsacvoyage/storage/AbstractTest.php';
use testsacvoyage\storage\AbstractTest;

require_once 'sacvoyage/storage/Gateway.php';
use sacvoyage\storage\Gateway;

require_once 'sacvoyage/storage/Table.php';
use sacvoyage\storage\Table;

require_once 'sacvoyage/storage/Filter.php';
use sacvoyage\storage\Filter;

require_once 'sacvoyage/Object.php';
use sacvoyage\Object;

class FilterTest extends AbstractTest {

	public function setUp() {
		$this->resetDatabase();	
		$this->fillDatabase();
	}

	/*
	 * select absolutely all document keys from database
	 */
	public function testFilterAll() {
		$keys=$this->_getFilteredKeys();
		
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newnote', '_rev'=>'1')),
				new Object(array('_id'=>'newbook', '_rev'=>'1')),
				new Object(array('_id'=>'newidea', '_rev'=>'1')),
				new Object(array('_id'=>'newnote', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'1')),
				new Object(array('_id'=>'newtask', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);

	}


	/*
	 * 
	 */
	public function testFilterNot() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array(
				'_not'=>new Object(array('_is'=>'number'))
			))
		)));
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newbook', '_rev'=>'1')),
				new Object(array('_id'=>'newidea', '_rev'=>'1')),
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterAnd() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'_and'=>array(
				new Object(array(
					'priority'=>new Object(array('_is'=>'number'))
				)), 
				new Object(array(
					'text'=>new Object(array('_regex'=>'\.*укроп\.*'))
				))
			)
		)));
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newnote', '_rev'=>'2'))
			),
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterOr() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array(
				'_or'=>array(
					new Object(array('_is'=>'number')), 
					new Object(array('_is'=>'string'))
				)
			))
		)));
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newnote', '_rev'=>'1')),
				new Object(array('_id'=>'newnote', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'1')),
				new Object(array('_id'=>'newtask', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterExists() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_exists'=>true))
		)));
		
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newnote', '_rev'=>'1')),
				new Object(array('_id'=>'newnote', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'1')),
				new Object(array('_id'=>'newtask', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);


		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_exists'=>false))
		)));

		$this->assertEquals(
			array(
				new Object(array('_id'=>'newbook', '_rev'=>'1')),
				new Object(array('_id'=>'newidea', '_rev'=>'1')),
			),
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterIs() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_is'=>'string'))
		)));
		
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);

	}

	/*
	 * 
	 */
	public function testFilterNis() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_nis'=>'number'))
		)));
		
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);

	}


	/*
	 * select where $.author.first='Льюис' and $.author.last='Кэрролл'
	 */
	public function testFilterEq() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'author'=>new Object(array('first'=>'Льюис', 'last'=>'Кэрролл'))
		)));
		$this->assertEquals(
			array(new Object(array('_id'=>'newbook', '_rev'=>'1'))),
			$keys
		);

		$keys=$this->_getFilteredKeys(new Object(array(
			'author'=>new Object(array(
				'first'=>new Object(array('_eq'=>'Льюис')), 
				'last'=>new Object(array('_eq'=>'Кэрролл'))
			))
		)));
		$this->assertEquals(
			array(new Object(array('_id'=>'newbook', '_rev'=>'1'))),
			$keys
		);
	}

	/*
	 * select where $.author.first='Льюис' and $.author.last='Кэрролл'
	 */
	public function testFilterIn() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'type'=>new Object(array('_in'=>array('book', 'idea')))
		)));
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newbook', '_rev'=>'1')),
				new Object(array('_id'=>'newidea', '_rev'=>'1'))
			),
			$keys
		);
	
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_in'=>array(5, '4', '')))
		)));
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newnote', '_rev'=>'1')),
				new Object(array('_id'=>'newnote', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'1')),
				new Object(array('_id'=>'newtask', '_rev'=>'2')),
				new Object(array('_id'=>'newtask', '_rev'=>'3'))
			),
			$keys
		);
	}


	/*
	 * 
	 */
	public function testFilterNe() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_ne'=>5))
		)));
		$this->assertEquals(
			array(
				new Object(array('_id'=>'newnote', '_rev'=>'1')),
				new Object(array('_id'=>'newbook', '_rev'=>'1')),
				new Object(array('_id'=>'newidea', '_rev'=>'1')),
			),
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterNin() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_nin'=>array(5, 3)))
		)));
		$expected=array(
			new Object(array('_id'=>'newnote', '_rev'=>'1')),
			new Object(array('_id'=>'newbook', '_rev'=>'1')),
			new Object(array('_id'=>'newidea', '_rev'=>'1'))
		);
		$this->assertEquals(
			$expected,
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterCompare() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'priority'=>new Object(array('_gt'=>4))
		)));
		$expected=array(
			new Object(array('_id'=>'newnote', '_rev'=>'2')),
			new Object(array('_id'=>'newtask', '_rev'=>'1')),
			new Object(array('_id'=>'newtask', '_rev'=>'2')),
			new Object(array('_id'=>'newtask', '_rev'=>'3'))
		);
		$this->assertEquals(
			$expected,
			$keys
		);
	}

	/*
	 * 
	 */
	public function testFilterRegex() {
		$keys=$this->_getFilteredKeys(new Object(array(
			'text'=>new Object(array('_regex'=>'\.*БНО\.*'))
		)));
		$expected=array(
			new Object(array('_id'=>'newtask', '_rev'=>'1')),
			new Object(array('_id'=>'newtask', '_rev'=>'2')),
			new Object(array('_id'=>'newtask', '_rev'=>'3'))
		);
		$this->assertEquals(
			$expected,
			$keys
		);
	}

	private function _getFilteredKeys($jsonFilter=array()) {
		$keySource=new Filter(
			new Table($this->getGateway(), 'alex_db_notes'),
			$jsonFilter
		);
		return iterator_to_array($keySource);
	}


}

?>
